package sporteam.web.server;

import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Logger;

import javax.jdo.PersistenceManager;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.json.JSONException;
import org.json.JSONObject;

import sporteam.common.PMF;
import sporteam.web.client.AEuser;
import sporteam.web.client.Activity;
import sporteam.web.client.Track;
import sporteam.web.client.UserAppData;

import com.c2dm.data.MessageUtil;
import com.google.gson.Gson;

public class UpdateUser extends HttpServlet {

	private static final Logger MyLog = Logger.getLogger(UpdateUser.class
			.getName());
	private static final String SendLogURL = "http://sporteamtest.appspot.com/SendLog";
	private static final long serialVersionUID = 1L;

	@Override
	public void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws IOException {
		try {
			doPost(req, resp);
		} catch (ServletException e) {
			MyLog.warning(e.toString());
		}
	}

	@Override
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html; charset=UTF-8");

		// get JsonObject
		JSONObject json = JsonUtils.RetrieveJsonFromRequest(request);
		Gson gson = new Gson();
		try {
			String update_info = (String) json.get("update_info");

			// handle update cases
			if (update_info.equals("track")) {
				// get track
				String TrackStr = (String) json.get("track");
				String facebook_ID = (String) json.get("facebook_ID");

				// update track in appengine database
				HandleNewTrack(gson.fromJson(TrackStr, Track.class),
						facebook_ID);
			} else if (update_info.equals("activity")) {
				String ActStr = (String) json.get("activity");
				HandleActivityUpdate(gson.fromJson(ActStr, Activity.class));
			} else if (update_info.equals("rename_track")) {
				long trackID = Long.parseLong((String) json.get("track_ID"));
				String facebookID = (String) json.get("facebook_ID");
				String newName = (String) json.get("name");
				HandleTrackRename(trackID, facebookID, newName);
			} else if (update_info.equals("delete_track")) {
				long trackID = Long.parseLong((String) json.get("track_ID"));
				String ownerID = (String) json.get("facebook_ID");
				HandleTrackDelete(trackID, ownerID);
			} else if (update_info.equals("update_track")) {
				String trackStr = (String) json.get("track");
				String ownerID = (String) json.get("facebook_ID");
				HandleTrackUpdate(gson.fromJson(trackStr, Track.class), ownerID);
			} else if (update_info.equals("update_track_synced")) {
				long trackID = Long.parseLong((String) json.get("track_ID"));
				String ownerID = (String) json.get("facebook_ID");
				String trackSynced = (String) json.get("sync_status");
				HandleTrackSyncUpdate(trackID, ownerID, trackSynced);
			} else if (update_info.equals("update_activity_synced")) {
				String activityID = (String) json.get("act_ID");
				String ownerID = (String) json.get("facebook_ID");
				String activitySynced = (String) json.get("sync_status");
				//HandleActivitySyncUpdate(activityID, ownerID, activitySynced);
			}
			else if (update_info.equals("update_activity_closed")) {
				String activityID = (String) json.get("act_ID");
				String ownerID = (String) json.get("facebook_ID");
				String activityClosed = (String) json.get("activity_status");
				HandleActivityClosed(activityID, ownerID, activityClosed);
			}
			
		} catch (JSONException e) {
			MyLog.warning(e.toString());
		}
	}

	// update regular track on appenigne
	private void HandleNewTrack(Track track, String facebook_ID) {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		MyLog.warning("handling new track");

		boolean trackFound = false;
		Object idInstance;
		AEuser ae_user = null;
		AEuser userTmp = null;
		// retrieve old user
		try {
			idInstance = pm.newObjectIdInstance(AEuser.class, facebook_ID);
			ae_user = (AEuser) pm.getObjectById(idInstance);

			userTmp = new AEuser(ae_user);

			for (Track t : userTmp.GetTracks()) {
				if (t.getDate() == track.getDate()) {
					MyLog.warning("track found and updated");
					userTmp.GetTracks().remove(t);
					userTmp.GetTracks().add(track);
					trackFound = true;
					break;
				}
			}

			// add track in case not found
			if (!trackFound) {
				MyLog.warning("track added to user");
				userTmp.GetTracks().add(track);
			}
			
			//update users competitions
			try{
			UserAppData.updateCompetitonByTrack(ae_user.GetFacebookID(), track);
			}
			catch(Exception e){
				MyLog.warning("Exception while updating competition");
				
			}
		} catch (Exception e) {
			MyLog.warning("HandleNewTrack aborted--");
			MyLog.warning(e.toString());
			return;
		}

		// update user in appengine
		userTmp.UpdateDate();
		pm.deletePersistent(ae_user);
		pm.makePersistent(userTmp);

		// close persistent manager
		pm.close();

	}

	void HandleActivityUpdate(Activity act) {
		MyLog.warning("handling activity update");
		boolean senderActFound = false, adresseeActFound = false;
		PersistenceManager pm = PMF.get().getPersistenceManager();
		AEuser sender;
		AEuser adressee;
		ArrayList<Activity> adresseeActivities = null;
		ArrayList<Activity> senderActivities = null;
		Activity updatedAct = null;

		try {
			sender = (AEuser) pm.getObjectById(AEuser.class, act.getSenderID());
			adressee = (AEuser) pm.getObjectById(AEuser.class,
					act.getReceiverID());

			senderActivities = sender.GetActivities();
			// iterate all current activities of sender
			for (Activity senderAct : senderActivities) {
				// in sender has current activity stored
				if (act.getActivity_id().equals(senderAct.getActivity_id())) {
					MyLog.warning("activity found! removing and adding new activity");
					senderActivities.remove(senderAct);
					senderActivities.add(act);
					updatedAct = act;
					senderActFound = true;
					break;
				}
			}

			adresseeActivities = adressee.GetActivities();

			// iterate all current activities of adressee
			for (Activity adresseeAct : adresseeActivities) {
				// in adresseee has current activity stored
				if (act.getActivity_id().equals(adresseeAct.getActivity_id())) {
					MyLog.warning("activity found! removing and adding new activity");
					adresseeActivities.remove(adresseeAct);
					adresseeActivities.add(act);
					updatedAct = act;
					adresseeActFound = true;
					break;
				}
			}

			// add new activity to both participants
			if (!senderActFound) // in case of new activity
			{
				updatedAct = act;
				sender.AddActivity(act);
			}

			if (!adresseeActFound) // in case of new activity
			{
				updatedAct = act;
				adressee.AddActivity(act);
			}

			/* send c2dm msg to reciever if needed --- disabled for now 
			try {
				if (act.getReceiverTrack() == null) // send msg to the one
													// recieving the activity
				{
					MessageUtil.sendInformativeMessage(
							adressee.GetFacebookID(),
							"track;" + sender.GetFirstName() + " "
									+ sender.GetLastName() + ";");
				} else // send msg to the one initiating the activity
				{
					MessageUtil.sendInformativeMessage(
							sender.GetFacebookID(),
							"track;" + adressee.GetFirstName() + " "
									+ adressee.GetLastName() + ";");
				}
			} catch (Exception e) {
				MyLog.warning("error on sending msg" + e.toString());
			}*/

		} catch (Exception e) {
			MyLog.warning("error on handling activity update");
			MyLog.warning(e.toString());
			return;
		}

		// update friends for sender
		UserLoadingUtils.UpdateUserFriends(sender, updatedAct);

		// updae friends for addresee
		UserLoadingUtils.UpdateUserFriends(adressee, updatedAct);

		// update both participants on appengine
		sender.UpdateDate();
		adressee.UpdateDate();

		AEuser senderBackUp = new AEuser(sender);
		pm.deletePersistent(sender);
		pm.makePersistent(senderBackUp);

		AEuser adresseeBackUp = new AEuser(adressee);
		pm.deletePersistent(adressee);
		pm.makePersistent(adresseeBackUp);

		MyLog.warning("saved activity for both sender and adressee");

		// close persistent manager
		pm.close();

	}

	void HandleTrackRename(long trackID, String facebookID, String newName) {
		MyLog.warning("handling track rename");

		PersistenceManager pm = PMF.get().getPersistenceManager();
		Object idInstance;
		AEuser ae_user = null;
		AEuser userTmp = null;
		// get old user
		try {
			idInstance = pm.newObjectIdInstance(AEuser.class, facebookID);
			ae_user = (AEuser) pm.getObjectById(idInstance);

			userTmp = new AEuser(ae_user);

			// updated track with the new name
			for (Track t : userTmp.GetTracks()) {
				if (t.getDate() == trackID) {
					MyLog.warning("track found and renamed");
					t.setName(newName);
					break;
				}
			}
		} catch (Exception e) {
			MyLog.warning("HandleTrackRename aborted--");
			MyLog.warning(e.toString());
			return;
		}

		// update user in appengine
		userTmp.UpdateDate();
		// delete adresee from appengine
		pm.deletePersistent(ae_user);
		pm.makePersistent(userTmp);

		// close persistent manager
		pm.close();
	}

	void HandleTrackUpdate(Track track, String facebookID) {
		MyLog.warning("handling track rename");

		PersistenceManager pm = PMF.get().getPersistenceManager();

		// get old user
		Object idInstance = pm.newObjectIdInstance(AEuser.class, facebookID);
		AEuser user = (AEuser) pm.getObjectById(idInstance);

		AEuser userTmp = new AEuser(user);

		// updated track with the new name
		try {
			for (Track t : userTmp.GetTracks()) {
				if (t.getDate() == track.getDate()) {
					MyLog.warning("track found and updated");
					userTmp.GetTracks().remove(t);
					userTmp.GetTracks().add(track);
					break;
				}
			}
		} catch (Exception e) {
			MyLog.warning(e.toString());
			return;
		}

		// update user in appengine
		userTmp.UpdateDate();
		// delete adresee from appengine
		pm.deletePersistent(user);
		pm.makePersistent(userTmp);

		// close persistent manager
		pm.close();
	}

	public void HandleTrackDelete(long track_ID, String facebook_ID) {
		MyLog.warning("handling track delete");

		PersistenceManager pm = PMF.get().getPersistenceManager();
		AEuser ae_user = null;
		AEuser userTmp = null;
		// get old user
		try {
			Object idInstance = pm.newObjectIdInstance(AEuser.class,
					facebook_ID);
			ae_user = (AEuser) pm.getObjectById(idInstance);

			userTmp = new AEuser(ae_user);

			// find track and delete it
			for (Track t : userTmp.GetTracks()) {
				if (t.getDate() == track_ID) {
					MyLog.warning("track found and deleted");
					userTmp.GetTracks().remove(t);
					break;
				}
			}
		} catch (Exception e) {
			MyLog.warning("HandleTrackDelete aborted--");
			MyLog.warning(e.toString());
			return;
		}

		// delete adresee from appengine
		pm.deletePersistent(ae_user);

		// update user in appengine
		userTmp.UpdateDate();
		pm.makePersistent(userTmp);

		// close persistent manager
		pm.close();
	}

	public void HandleTrackSyncUpdate(long track_ID, String facebook_ID,
			String activity_sync_status) {
		MyLog.warning("handling track sync update");

		PersistenceManager pm = PMF.get().getPersistenceManager();
		AEuser ae_user = null;
		AEuser userTmp = null;

		boolean IsSynced = false;
		if (activity_sync_status.equals("synced"))
			IsSynced = true;

		// get old user
		try {
			Object idInstance = pm.newObjectIdInstance(AEuser.class,
					facebook_ID);
			ae_user = (AEuser) pm.getObjectById(idInstance);

			userTmp = new AEuser(ae_user);

			// find track and delete it
			for (Track t : userTmp.GetTracks()) {
				if (t.getDate() == track_ID) {
					MyLog.warning("track found and sync updated");
					t.setSynced(IsSynced);
					break;
				}
			}
		} catch (Exception e) {
			MyLog.warning("HandleTrackDelete aborted--");
			MyLog.warning(e.toString());
			return;
		}

		// delete adresee from appengine
		pm.deletePersistent(ae_user);

		// update user in appengine
		userTmp.UpdateDate();
		pm.makePersistent(userTmp);

		// close persistent manager
		pm.close();
	}

	private void HandleActivityClosed(String activityID,
			String facebook_ID, String activityStatus) {
		/*
		MyLog.warning("handling activity closed");
		boolean senderActFound = false, adresseeActFound = false;
		PersistenceManager pm = PMF.get().getPersistenceManager();
		AEuser sender;
		AEuser adressee;
		ArrayList<Activity> adresseeActivities = null;
		ArrayList<Activity> senderActivities = null;
		Activity updatedAct = null;

		try {
			sender = (AEuser) pm.getObjectById(AEuser.class, act.getSenderID());
			adressee = (AEuser) pm.getObjectById(AEuser.class,
					act.getReceiverID());

			senderActivities = sender.GetActivities();
			// iterate all current activities of sender
			for (Activity senderAct : senderActivities) {
				// in sender has current activity stored
				if (act.getActivity_id().equals(senderAct.getActivity_id())) {
					MyLog.warning("activity found! removing and adding new activity");
					senderActivities.remove(senderAct);
					senderActivities.add(act);
					updatedAct = act;
					senderActFound = true;
					break;
				}
			}

			adresseeActivities = adressee.GetActivities();

			// iterate all current activities of adressee
			for (Activity adresseeAct : adresseeActivities) {
				// in adresseee has current activity stored
				if (act.getActivity_id().equals(adresseeAct.getActivity_id())) {
					MyLog.warning("activity found! removing and adding new activity");
					adresseeActivities.remove(adresseeAct);
					adresseeActivities.add(act);
					updatedAct = act;
					adresseeActFound = true;
					break;
				}
			}

			// add new activity to both participants
			if (!senderActFound) // in case of new activity
			{
				updatedAct = act;
				sender.AddActivity(act);
			}

			if (!adresseeActFound) // in case of new activity
			{
				updatedAct = act;
				adressee.AddActivity(act);
			}

		} catch (Exception e) {
			MyLog.warning("error on handling activity update");
			MyLog.warning(e.toString());
			return;
		}

		// update friends for sender
		UserLoadingUtils.UpdateUserFriends(sender, updatedAct);

		// updae friends for addresee
		UserLoadingUtils.UpdateUserFriends(adressee, updatedAct);

		// update both participants on appengine
		sender.UpdateDate();
		adressee.UpdateDate();

		AEuser senderBackUp = new AEuser(sender);
		pm.deletePersistent(sender);
		pm.makePersistent(senderBackUp);

		AEuser adresseeBackUp = new AEuser(adressee);
		pm.deletePersistent(adressee);
		pm.makePersistent(adresseeBackUp);

		MyLog.warning("saved activity for both sender and adressee");

		// close persistent manager
		pm.close();
*/
	}

}